import os
from multiprocessing import Pool, Value
from sys import stdout

def get_files(directory, format):
    return [os.path.join(directory, filename)
            for filename in sorted(os.listdir(directory))
            if filename[-4:] == format]

total, progress = 0, 0

def map_reduce(func, args, options):
    if options.verbose:
        initialize_status_bar(len(args))
    results = []
    append = results.append
    processors = options.processors
    if processors is None or processors > 1:
        p = Pool() if processors is None else Pool(processors)
        for arg in args:
            append(p.apply_async(func, (arg,), options.__dict__, task_finished))
        p.close()
        p.join()
        #print results
        results = (result.get() for result in results)
    else:
        for arg in args:
            append(func(arg, **options.__dict__))
            task_finished()
    return filter(lambda result: result is not None, results)

def initialize_status_bar(new_total=1):
    global total, progress
    total = new_total
    progress = Value('I', 0)
    update_status_bar()

def task_finished(a=None):
    """Call this after finishing a task to update the status bar."""
    global progress, total
    progress.acquire()
    progress.value += 1
    update_status_bar(progress.value/float(total))
    progress.release()

def update_status_bar(frac=0, size=65):
    """Prints a status bar to the terminal with the given fraction filled."""
    perc = int(size*frac)
    out = '\r['
    for i in range(perc): out += '='
    for i in range(size-perc): out += ' '
    stdout.write(out + '] {0:%}'.format(frac))
    #print out + '] {0:%}'.format(frac)

def raw_string(s):
    if isinstance(s, str):
        s = s.encode('string-escape')
    elif isinstance(s, unicode):
        s = s.encode('unicode-escape')
    return s

def make_sure_path_exists(path):
    """Creates the supplied path. Raises OS error if the path cannot be
    created."""
    try:
      os.makedirs(path)
    except OSError:
      if not os.path.isdir(path):
        raise

def get_unmasked(data):
    """Returns all of the values that are not outliers."""
    return data[~data.mask].reshape(-1, data.shape[1])

def get_masked(data):
    """Returns all identified outliers"""
    return data[data.mask].data.reshape(-1, data.shape[1])
